使用 Docker Compose 一次建立 Nginx 伺服器 與 Cerbot(SSL自動憑證)
前言
網路發展迅速,人們使用網際網路於網頁上獲取新知,網站之間傳輸需經由安全加密以避免有心人士從中做壞,因此SSL(Secure Sockets Layer)憑證是一種用於網站的安全證書,它可以保證在傳送數據時保持安全性。通常SSL憑證來源可以由SSL憑證供應商取得,不過可能需要付出一定非用。當然也有免費的來源,而免費的憑證服務有效期限為90天,一段時間就得重複同樣操作其實浪費時間與心力,若有自動化的方式何不為樂呢。因此這次帶來容器化方式一次將所有服務設置完成。
什麼是Docker & Docker Compose?
Docker 將軟體封裝到名為容器的標準化單位,容器是在作業系統層上虛擬化,並將容器獨立環境且直接使用系統OS資源,無須安裝/虛擬化作業系統。透過Docker可以最小化方式建立微服務且能快速啟動、停止、刪除等操作。其中Jekins與SonarQube都有各自的image提供在Docker hub上。
Docker Compose是為了協助定義和運行多容器應用程式而開發的工具,利用 YAML 檔案來配置需要的服務以及服務的環境設定。
什麼是Nginx?
Nginx是非同步框架的網頁伺服器,也可以用作反向代理、負載平衡器和HTTP快取。與Apache網頁伺服器都相當知名,Nginx設置簡易,記憶體消耗低,反向代理&負載平衡功能也很不錯
什麼是SSL憑證?
SSL是Secure Socket Layer的縮寫,是一種資訊傳輸的加密技術,能夠加密兩個網站之間互相傳輸的資料,讓他人無法取得您的網站與客戶之間的隱私訊息。經過SSL憑證加密成功的網站,網址會由http變成https。
為什麼需要SSL憑證?
剛剛提到SSL是資料傳輸的加密技術,可以知道當網站與使用者互動時輸入的資料是有被加密過的。那反之,如果沒有SSL不就意謂著你的資料是裸露的,有心人士若攔截封包,就可以輕易取得你的資料,因為沒有加密,不需要解密過程。
實作重點
- 環境準備
- 準備域名
- 安裝Docker
- 安裝Docker-Compose
- 服務架設 for 一般域名憑證申請方式
- 設置docker-compose.yml容器化服務的環境與配置
- 啟動主要容器服務
- 設置docker-composeLE.yml,首次憑證申請容器服務
- 啟動首次憑證申請容器服務,完成SSL憑證申請
- Nginx SSL設置
- 切換容器服務啟動自動SSL憑證申請
- 服務架設 for 萬用子域憑證申請方式
- DNS服務管理權限金鑰申請
- 設置docker-compose.yml、docker-composeLE.yml容器化服務的環境與配置
- 啟動主要容器服務
- 啟動首次憑證申請容器服務,完成SSL憑證申請
- Nginx SSL設置
- 切換容器服務啟動自動SSL憑證申請
環境準備
環境只要安裝Docker跟Docker-Compose而已,可以知道接下來的設置都會在容器中,大幅降低環境汙染
準備域名
域名就跟車牌一樣有貴的有便宜的,而免費也有。freenom提供許多免費一年的域名供使用者申請。
輸入你想要的域名,從圖中可以看到freenom給予一些選擇, 有些可以使用有些已經被使用過了
接著選擇使用期限,一年之前都是免費的。如果一年到期的話其實還可以繼續申請同一個,也還是免費。而且在過期前一個月就可以先續約,相當於優先權。
申請完畢後,前往我的域名以管理域名
在域名這邊我們可以設定該域名指向的IP位置,我的域名是指到github page的服務上,若自己有虛擬機也可以指向自己的公開IP上
安裝Docker
Docker安裝指令如下:
1 | # 移除舊版本的docker |
給予使用者Docker權限
1 | # 將$USER加入docker群組 |
安裝Docker-Compose
Docker Compose安裝指令如下:
1 | sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose |
服務架設 for 一般域名憑證申請方式
一般域名在憑證申請上只要證明該域名是你的即可,通常只要依照規定在伺服器內設置路由,憑證機器人會在該路由處產生一個token檔,讓它驗證是否能夠順利訪問,若訪問成功憑證機器人就認可該域名是你擁有的。
設置docker-compose.yml容器化服務的環境與配置
我們的docker-compose.yml總共會有3個角色
- 網頁伺服器: Nginx
- 開發的服務: 前端、後端等等
- 證書機器人: Cerbot
至少會有3個容器服務,這次開發的服務我使用Jenkins作為範例,以下是我的docker-compose.yml:
1 | version: '3.1' |
設置Nginx伺服器設定檔
從docker-compose.yml設定檔中可以得知,檔案需撰寫於nginx目錄下,在首次服務運行時我們會做首次憑證申請,因此這邊的設定只為了第一次的憑證訪問
1 | server { |
啟動主要容器服務
我們已經建立好需要的服務在docker-compose.yml上了,接著只要使用docker-compose的指令就可以一次建立好容器。
通常單一域名的憑證申請會須要驗證特定目錄是否能正常訪問且含有服務建立好的標誌,因此先啟動容器服務讓瀏覽器輸入域名可以正常訪問
在docker-compose.yml檔案的目錄下執行建置指令:
1 | # 執行已寫好的docker-compose.yml |
設置docker-composeLE.yml,首次憑證申請容器服務
撰寫docker-composeLE.yml
1
2
3
4
5
6
7
8
9version: '3.1'
services:
certbot:
image: certbot/certbot
command: certonly --webroot --webroot-path /var/www/certbot/ -d ${HOST_DOMAIN} --email ${HOST_EMAIL} --agree-tos
volumes:
- ./nginx/certbot/www/:/var/www/certbot/:rw
- ./nginx/certbot/conf/:/etc/letsencrypt/:rw撰寫環境變數(.env)
在docker-composeLE.yml的certbot command可以看到有使用到環境變數,而這部分可以設定在.env檔中,讓docker-compose自動讀取
1
2HOST_DOMAIN=<要註冊的域名>
HOST_EMAIL=<信箱>
啟動首次憑證申請容器服務,完成SSL憑證申請
指定啟動docker-composeLE.yml的服務,接著會執行cerbot預先寫好的command
1 | docker-compose -f docker-composeLE.yml up |
基本上我們在此可看到憑證申請過程,若失敗則會輸出相關錯誤訊息於終端機上
將Nginx伺服器設定改為SSL,並重新載入Nginx
1 | server { |
完成後重新整理nginx伺服器
1 | docker-compose restart |
訪問自己的域名看看有沒有成功開啟SSL憑證吧
更新憑證容器,完成自動化更新SSL憑證
還記得docker-compose.yml上有撰寫cerbot容器嗎,透過再次啟動下方指令,將首次申請用的容器替代即可
1 | docker-compose up -d |
服務架設 for 萬用子域憑證申請方式
DNS服務管理權限金鑰申請
首先前往cloudflare網站登入後,點選個人帳戶的API Token(如圖)
接著點選建立Token,會到下圖頁面,我們需要給予DNS編輯權限並且設定區域資源給予我們要使用的網域Domin
建立完成後我們會獲得一串金鑰token,將這串金鑰token填寫到 nginx/ssl/cloudflare.ini
,覆蓋掉”your_token”
1 | dns_cloudflare_api_token = your_token |
前往API和服務→憑證建立服務帳戶
輸入基本資訊
設定將DNS權限給予服務
建立完畢後,選取我們建立好的服務帳戶
前往金鑰選項並新增金鑰
選擇JSON格式,建立完畢後將自動下載金鑰
下載完成後我們將json內容複製填寫到 nginx/ssl/google.json
,下方為我們需要看到的格式
1 | { |
設置docker-compose.yml容器化服務的環境與配置
撰寫docker-composeLE.yml
因為使用的dns服務商不同,我們的cerbot image和指令也不同,
因此要檢查docker/docker-compose.yml
、docker/docker-composeLE.yml
必須與下方一致
docker/docker-compose.yml
(這裡只列出cerbot服務)1
2
3
4
5
6
7
8
9certbot:
image: certbot/dns-cloudflare
container_name: certbot
volumes:
- ../nginx/certbot/conf:/etc/letsencrypt
- ../nginx/certbot/logs:/var/log/letsencrypt
- ../nginx/certbot/data:/var/www/certbot
- ../nginx/ssl:/secrets
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"docker/docker-composeLE.yml
1
2
3
4
5
6
7
8
9
10
11version: '3.1'
services:
certbot:
image: certbot/dns-cloudflare
command: certonly --expand -d ${HOST_DOMAIN} -d ${WILDCARD_DOMAIN} --preferred-challenges dns --dns-cloudflare --dns-cloudflare-credentials /secrets/cloudflare.ini --email ${HOST_EMAIL} --agree-tos --server https://acme-v02.api.letsencrypt.org/directory
volumes:
- ../nginx/certbot/conf:/etc/letsencrypt
- ../nginx/certbot/logs:/var/log/letsencrypt
- ../nginx/certbot/data:/var/www/certbot
- ../nginx/ssl:/secrets撰寫環境變數(.env)
在docker-composeLE.yml的certbot command可以看到有使用到環境變數,而這部分可以設定在.env檔中,讓docker-compose自動讀取
1
2
3HOST_DOMAIN=<要註冊的域名>
WILDCARD_DOMAIN=<要註冊的萬用域名>
HOST_EMAIL=<信箱>
撰寫docker-composeLE.yml
因為使用的dns服務商不同,我們的cerbot image和指令也不同,
因此要檢查docker/docker-compose.yml
、docker/docker-composeLE.yml
必須與下方一致
docker/docker-compose.yml
(這裡只列出cerbot服務)1
2
3
4
5
6
7
8
9certbot:
image: certbot/dns-google
container_name: certbot
volumes:
- ./nginx/certbot/conf:/etc/letsencrypt
- ./nginx/certbot/logs:/var/log/letsencrypt
- ./nginx/certbot/data:/var/www/certbot
- ./nginx/ssl:/secrets
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"docker/docker-composeLE.yml
1
2
3
4
5
6
7
8
9
10
11version: '3.1'
services:
certbot:
image: certbot/dns-google
command: certonly --expand -d ${HOST_DOMAIN} -d ${WILDCARD_DOMAIN} --preferred-challenges dns --dns-google --dns-google-credentials /secrets/google.json --email ${HOST_EMAIL} --agree-tos --server https://acme-v02.api.letsencrypt.org/directory --dry-run
volumes:
- ./nginx/certbot/conf:/etc/letsencrypt
- ./nginx/certbot/logs:/var/log/letsencrypt
- ./nginx/certbot/data:/var/www/certbot
- ./nginx/ssl:/secrets撰寫環境變數(.env)
在docker-composeLE.yml的certbot command可以看到有使用到環境變數,而這部分可以設定在.env檔中,讓docker-compose自動讀取
1
2
3HOST_DOMAIN=<要註冊的域名>
WILDCARD_DOMAIN=<要註冊的萬用域名>
HOST_EMAIL=<信箱>
啟動主要容器服務
我們已經建立好需要的服務在docker-compose.yml上了,接著只要使用docker-compose的指令就可以一次建立好容器。
通常單一域名的憑證申請會須要驗證特定目錄是否能正常訪問且含有服務建立好的標誌,因此先啟動容器服務讓瀏覽器輸入域名可以正常訪問
在docker-compose.yml檔案的目錄下執行建置指令:
1 | # 執行已寫好的docker-compose.yml |
啟動首次憑證申請容器服務,完成SSL憑證申請
指定啟動docker-composeLE.yml的服務,接著會執行cerbot預先寫好的command
1 | docker-compose -f docker-composeLE.yml up |
基本上我們在此可看到憑證申請過程,若失敗則會輸出相關錯誤訊息於終端機上
將Nginx伺服器設定改為SSL,並重新載入Nginx
1 | server { |
完成後重新整理nginx伺服器
1 | docker-compose restart |
訪問自己的域名看看有沒有成功開啟SSL憑證吧
更新憑證容器,完成自動化更新SSL憑證
還記得docker-compose.yml上有撰寫cerbot容器嗎,透過再次啟動下方指令,將首次申請用的容器替代即可
1 | docker-compose up -d |
結語
透過Docker compose方式使我們無須手動安裝Nginx以及憑證服務,大部分透過設定即可。甚至今後只需要做好範本,就可以很便捷佈署。